
package it.ibgka;

import it.enrollement.System_Param;
import it.ibs.IB_BLS;
import it.ibs.IB_DSA;
import it.user.User;
import it.utils.Hash;
import java.util.Random;
import jpair.pairing.BigInt;
import jpair.pairing.Point;




/**
 * Protocol IB-DB was obtained with minor changes from an elliptic version of the 
protocol for static groups given in Dutta and Barua [DUTTA2008PROVABLY]. In theis version of protocol is used IB_BLS signature scheme.
 * 
 * [DUTTA2008PROVABLY] Dutta, Ratna and Barua, Rana. Provably secure constant round contributory group key agreement in dynamic setting. IEEE. p. 2007--2025 2008
 *   
 * 
 * @author Francesco Rossi
 * @version 0.1
 * 
 */
public class IB_BD_DSA {

    boolean flag = false;
    boolean sign = true;
    System_Param parameter;
    User[] m;
    int n;
    Random rnd;
    IB_DSA a;

    public boolean getFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public IB_BD_DSA(User[] m, int n, System_Param param) {
        this.m = m;
        this.n = n;
        parameter = param;
        a = new IB_DSA(param);
    }

    public void Round1() {

        int i;
        Point Z;
        BigInt nn;


        for (i = 0; i < n; i++) {
            rnd = new Random();

            // choise ni
            m[i].getIbgka().setNi(new BigInt(parameter.getE().getGroupOrder().bitLength(), rnd));
            //  Zi = niP
            m[i].getIbgka().setZi(parameter.getE().getCurve().multiply(parameter.getP(), m[i].getIbgka().getNi()));

            m[i].getIbs().setM2sigma(a.sign(m[i].getIbgka().getZi().toString(), m[i].getKdsa()));

        }


    }

    public void Round2() {
        BigInt mi;
        Hash ut = new Hash();
        int i, is, ip;
        Point X, Y, NZP;

        BigInt nn;
        try {



            for (i = 0; i < n; i++) {
                ip = ((n + i - 1) % n);
                is = (i + 1) % n;

                if (n == 2) {
                    if (a.vrf(m[is].getIbgka().getZi().toString(), m[is].getID(), m[is].getIbs().getM2sigma(),m[is].getTid())) {
                        flag = true;
                        //    System.out.println("Utente "+i+"Verifica firme"+is);  
                    }

                } else if (n > 2) {
                    if ((a.vrf(m[is].getIbgka().getZi().toString(), m[is].getID(), m[is].getIbs().getM2sigma(),m[is].getTid())) && (a.vrf(m[ip].getIbgka().getZi().toString(), m[ip].getID(), m[ip].getIbs().getM2sigma(),m[ip].getTid()))) {
                        flag = true;

                        //     System.out.println("Utente "+i+"Verificate firme "+ip+","+is);  
                    }
                }


            }


            // System.out.println("flag="+flag);  
            if (flag) {
                for (i = 0; i < n; i++) {



                    is = (i + 1) % n;

                    ip = ((n + i - 1) % n);



                    //   System.out.println("System out println ="+is+","+ip);

                    // Xi = niZi+i
                    X = parameter.getE().getCurve().multiply(m[is].getIbgka().getZi(), m[i].getIbgka().getNi());

                    //  niZi-1 
                    NZP = parameter.getE().getCurve().multiply((m[ip].getIbgka().getZi()), m[i].getIbgka().getNi());
                    //  X = m[i].getE().getCurve().multiply(m[is].getZi(), m[i].getNi());
                    m[i].getIbgka().setXi(X);

                    // Yi = Xi - niZi-1
                    m[i].getIbgka().setYi(parameter.getE().getCurve().subtract(X, NZP));


                    m[i].getIbs().setM2sigma(a.sign(m[i].getIbgka().getYi().toString(), m[i].getKdsa()));




                }
            }
        } catch (Exception c) {
            c.printStackTrace();
        }
    }

    public void KeyDerivation() {
        int i, j, is, ip, ind, ind2;
        Point K, sum = null;

        Point kk = null;
        BigInt nn;





        if (flag) {
            for (i = 0; i < n; i++) {
                // Verify Yi
                for (j = 0; j < n - 1; j++) {
                    is = (i + j + 1) % n;
                    if ((!a.vrf(m[is].getIbgka().getYi().toString(), m[is].getID(), m[is].getIbs().getM2sigma(),m[is].getTid()))) {
                        flag = false;
                    }
                }
            }
        }


        // For each mi 
        if (flag) {
            for (i = 0; i < n; i++) {

                kk = m[i].getIbgka().getXi();
                sum = m[i].getIbgka().getXi();

                // Compute Xi
                for (j = 0; j < n - 1; j++) {
                    is = (i + j + 1) % n;



                    // System.out.println("Calcolo  X["+is+"]=X["+((i+j)%n)+"]+Y["+is+"]");

                    // Compute Xj with j != i    
                    kk = parameter.getE().getCurve().add(kk, m[is].getIbgka().getYi());



                    // K = Xi+ Xj
                    sum = parameter.getE().getCurve().add(sum, kk);


                }

                //    System.out.println("**********************************************");


                m[i].getIbgka().setKi(sum);
                //    System.out.println("User "+i+" Compute the key ");   
                // System.out.println(m[i].getIbgka().getKi().toString());   

            }
        }



    }
}
